react

[React] 1. Introducing JSX and DOM

9 min read|17. 5. 15.

JSX란 무엇인가

const element = <h1> Hello, world!</h1>

JSX라고 불리는 이 구문은 string도 아니고 HTML도 아닙니다. React 라이브러리에서 UI를 구성할 때 사용하는 구문으로 JavaScript의 extension이라고 할 수 있습니다.(물론, 사용하지 않을 수도 있습니다.) 타 프레임워크에서 사용했던 템플릿 엔진이라고 불리는 것들과 유사한 문법을 취하며(생김새만), JavaScript의 모든 기능을 제공합니다.

JSX에 표현식 포함하기

자바스크립트의 표현식을 {}으로 묶어 JSX에 삽입할 수 있습니다. 기존의 템플릿 엔진에서 사용했던 방법과 비슷합니다. ES6에서 도입된 Template literal과도 비슷한 모습을 보입니다. 코드를 살펴보겠습니다.

const element = <h1>Hi!</h1>
ReactDOM.render(element, document.getElementById('root'))
//이 코드는 다음 포스팅에서 설명하며, 다음 예제 코드부터는 추가하지 않습니다.

위와 같이 element라는 객체를 만들어서 render()메소드에 전달하여 렌더링할 수 있습니다.

const element = <h1>1 + 1 = {1 + 1}</h1>

{}내부에서 자바스크립트 문법을 그대로 사용할 수도 있습니다.

JSX는 결국 표현식입니다.

컴파일이 끝나면 JSX 표현식은 일반 자바스크립트 객체가 됩니다.

let url = 'api/get/someting'
const element = <img src={url} />

JSX로 HTML 태그의 속성 값을 지정하고자 할 때는 ""(double quote)를 사용하지 않습니다. 사용하게 되면 JSX는 속성을 표현식이 아닌 문자열 리터럴로 인식하게 됩니다. 위 img태그의 경우처럼 태그가 비어있으면 />로 바로 닫아줘야 합니다. 자식 컴포넌트가 없거나 한 줄로 element 작성이 끝나는 경우에는 닫힘 태그로 self-close를 해줍니다.

const element = (
  <div>
    <h1>Hi</h1>
    <h2>1 + 1 = {1 + 1}</h2>
  </div>
)

위의 같은 경우처럼 HTML의 문법을 사용하여 태그들을 계층화하여 구성할 수 있습니다. 하지만 이 때 주의할 사항이 한 가지 있습니다. 반드시 루트 노드(Root Node)로 하나의 노드를 지정해야 한다는 것입니다. ReactDOM은 오직 하나의 루트 노드만 렌더링하기 때문에 다음의 경우는 렌더링하지 못합니다.

//Error!
const element = (
    <h1>Hi</h1>
    <h2>1 + 1 = {1 + 1}</h2>
);

동일 depth에 존재하는 element가 여러 개 존재하기 때문에 error가 발생하게 됩니다. 여러 개의 element들을 계층화하는 경우에는 이전의 예제 코드처럼 element들을 div태그로 감싸줘야 합니다.

기본적으로 React DOM은 렌더링하기 전에 JSX에 임베디드 된 모든 값을 이스케이프 처리합니다. 따라서 응용프로그램에 명시적으로 작성되지 않은 것을 삽입할 수 없고 XSS 공격을 방지할 수 있습니다.

DOM Elements

React는 성능과 크로스 브라우징 이슈를 해결하기 위해 브라우저로부터 독립적인 DOM 체계를 구축하고 있습니다. 그렇기 때문에 기존의 HTML 속성과 다른 점이 존재합니다.

Camel-Case Attributes

기본적으로 React에서는 모든 DOM 속성 또는 이벤트 핸들러를 Camel-case로 처리해야 합니다.

다른 Attributes

style

style 속성은 camelCase를 기반으로 작성된 style JavaScript 객체로 설정합니다. 모든 DOM의 속성과 일치하여, 원래 CSS에서 사용하던 속성들을 camelCase로 변경해서 사용할 수 있습니다.

const headerStyle = {
  backgroundColor: '#EEE';
  borderRadius: '5px';
};

const element = (
    <div style={headerStyle}>Apply style as camelCase</div>
);

className

기본적으로 HTML에서는 태그에 class를 지정해줄 때, <div class="container"></div>와 같은 방식을 사용했습니다. 그러나 React에서는 className이라는 속성을 통해 접근합니다. 다음과 같이 나타낼 수 있습니다.

const container = (<div className="container"></div>);

cf> JSX 속성값에는 항상 double quote를 사용합니다. JSX 속성값을 제외한 나머지 경우에 대해서는 single quote를 사용합니다. 강제적인 것이 아닌 airbnb 에서 제공하는 React convention 입니다.

onChange

이 속성을 가지고 있는 필드가 변경될 때마다 이벤트가 발생합니다. React에서는 실시간으로 사용자 입력을 처리하기 위한 방법으로 이벤트를 사용합니다.

<input onChange={this.handleChange} />

위 예제 코드에서는 input태그에 event가 발생할 때마다 handleChange라는 메소드가 호출됩니다.

checked

input태그 중 checkbox타입 또는 radio타입에서 지원되는 checked 속성입니다. 이 속성은 controlled components에 대해서 사용할 때 유용합니다.

value

value 속성은 inputtextarea태그에 대해 지원되는 속성입니다. 이 속성을 통하여 요소의 값을 설정할 수 있습니다. 하지만 이 값은 DOM의 값보다 우선됩니다. 그렇기 때문에 이 속성은 controlled components에 대해서 사용할 때 유용합니다. 초기값만 지정하려는 경우에는. 즉 uncontrolled components에 대해서는 defaultValue 속성을 사용할 수 있습니다.

defaultValue, defaultChecked

<textarea><input type='text'>에 대해서 지원합니다. 또한 type=checkboxtype=radio타입의 <input>태그에 대해서는 defaultChecked를 지원합니다.

<input type="text" defaultValue="Jbee" />

htmlFor

const element = (
  <div>
    <label for="name">Name: </label>
    <input type="text" />
  </div>
)
//"Warning: Unknown DOM property for. Did you mean htmlFor?
//  in label
//  in div"

for를 대체하는 htmlFor입니다. for속성을 사용하려고 하면 warning이 발생합니다.

const element = (
  <div>
    <label htmlFor="name">Name: </label>
    <input type="text" />
  </div>
)

JavaScript 문법의 for 예약어와 겹치기 때문에 htmlFor가 생겨났습니다.

dangerouslySetInnerHTML

이 속성은 DOM에서 사용하던 innerHTML 속성을 대체하기 위해 만들어졌습니다. 코드에서 HTML을 설정하는 것은 XSS 공격에 노출되기 쉽기 때문에 위험합니다. 그렇기 때문에 React에서는 이 속성 사용을 최소화하기 위해 장치를 마련해놓은 것입니다.

function innerHTML() {
  return { __html: 'Dangerous inner html!' }
}

function component() {
  return <div dangerouslySetInnerHTML={innerHTML()} />
}

그럼에도 불구하고 dangerouslySetInnerHTML 속성을 사용하려면 위의 예제 코드와 같이 __html이라는 키 값과 함께 객체를 전달하여 사용할 수 있습니다.

React와 관련된 포스트는 Github Repository에서 실시간 피드를 받으실 수 있습니다.

References